import Vue from 'vue'
import {rules,common,axios,getByteLen,axiosPost,msg,addClass,removeClass,hasClass} from './directives.config.js'
// wpg-validator 指令
Vue.directive('wpg-validator',{
    inserted:function(el,bind){
        el.setAttribute('wpg-validator',bind.expression); // 将验证规则绑定到DOM
        let validateRuleArr = bind.expression.split('|'); // 将验证规则拆分为数组    
        let validatorDirection = el.getAttribute('validator-placement'); // 获取提示文字的方向
        let validatorClassName = "validation-tips-wrap"; // 提示文字的类名     
        let validationBox = document.createElement("div"); // 包裹盒子 
        let validationTipsWrap = document.createElement("div"); // Tips
        let msg = "";
        let msgMaxWidth = 200;
        let msgWidth = null;
        if(validatorDirection){
            // 文字提示的方向 默认为向下居中 可以配置 top right bottom left 四个方向
            validatorClassName += "-"+validatorDirection;
        };
        // 嵌套处理
        el.parentNode.appendChild(validationBox);
        validationBox.appendChild(el); 
        validationBox.appendChild(validationTipsWrap);
        // 设置属性    
        validationBox.className = "validation";
        validationBox.style.position = "relative";
        validationBox.style.display = "inline-block";
        validationTipsWrap.className = validatorClassName;
        // 添加提示信息位置
        addPostion();
        // 提示信息为多行
        if((msg.length*13) < 200){msgWidth = msg.length*13;}else{msgWidth = msgMaxWidth;};
        validationTipsWrap.style.width = msgWidth+'px';
        validationTipsWrap.innerText = msg;
        validationTipsWrap.style.display = "none";
        // 得到焦点的时候改样式
        el.addEventListener('focus',function(){
            removeClass(el,'validator-input-blur');
            addClass(el,'validator-input-focus');
            //el.style.color = "#333";
            //el.style.borderColor = "#49d";
            //validator-input-focus
        });
        // 失去焦点的时候进行验证
        el.addEventListener('blur',function(event){
            checkedfun();
        });
        // 当改变的时候进行验证
        el.addEventListener('keyup',function(){
            checkedfun();
        });
        // 循环进行验证
        function checkedfun(){
            // 循环验证
            for(let i=0; i<validateRuleArr.length; ++i){
                // 处理只传递字符串 require emial phone 类型
                if(validateRuleArr[i].indexOf('(') == -1){
                    if(rules[validateRuleArr[i]].checkFun){
                        if(!rules[validateRuleArr[i]].checkFun(el.value)){
                            // tipMsg(rules[validateRuleArr[i]].message);
                            isTipMsg(validateRuleArr[i],rules[validateRuleArr[i]].message);
                            return false;
                            break;
                        }else{
                            removeTips();
                        };
                    }else if(rules[validateRuleArr[i]].regex){
                        if(!rules[validateRuleArr[i]].regex.test(el.value)){
                        // tipMsg(rules[validateRuleArr[i]].message);
                        isTipMsg(validateRuleArr[i],rules[validateRuleArr[i]].message);
                        return false;
                        break;
                    }else{
                        removeTips();
                    };
                };
                }else{          
                    // 处理函数类型 拿到方法名
                    let funName = validateRuleArr[i].match(/^[\w]*\(/)[0].replace(/\(/,''); // 拿到设置的方法名
                    let value = validateRuleArr[i].slice(0,validateRuleArr[i].length-1).replace(funName+'(','');// 拿到传递过来的参数
                    // 两种情况特殊处理 regex() 以及 remote()
                    if(funName == 'regex'){ // 处理 regex
                        if(!eval(value).test(el.value)){
                            // tipMsg("请输入正确的格式");
                            isTipMsg('regex','请输入正确的格式');
                            return false;
                            break;
                        }else{
                            removeTips();
                        };
                    }else if(funName == 'remote'){
                        el.setAttribute('remotestate',false);
                        tipMsg("正在验证");
                        axiosPost(eval(value),{value:el.value},function(res){
                            if(res.data.code != 200){
                                el.setAttribute('remotestate',false);
                                tipMsg(res.data.msg);
                            }else{
                                el.removeAttribute('remotestate');
                                removeTips();
                            };
                        });
                    }else{
                    // 处理传递过来的是函数 min() max() minlength() maxlength() 类型 
                    if(rules[funName].checkFun){
                        // 考虑 会传递多个参数 所以现在将传递的参数作为对象进行传递
                        if(!rules[funName].checkFun(el.value,value.split(','))){
                            // tipMsg(rules[funName].message);
                            isTipMsg(funName,rules[funName].message);
                            return false;
                            break;
                        }else{
                            removeTips();
                        };
                    }else if(rules[funName].regex){
                        if(!rules[funName].regex.test(el.value)){
                            // tipMsg(rules[funName].message);
                            isTipMsg(funName,rules[funName].message);
                            return false;
                            break;
                        }else{
                            removeTips();
                        };
                    };
                  };
                };
            };      
        };
        // 查看是否配置了提示信息
        function isTipMsg(target,defval){
            let msg = el.getAttribute("validator-errormsg-"+target);
            if(!msg){msg = defval;};
            tipMsg(msg);
        };
        // 添加提示信息
        function tipMsg(msg){
            //el.style.borderColor = "#c33";
            //el.style.color = "#cb3333";
            removeClass(el,'validator-input-focus');
            addClass(el,'validator-input-blur');
            validationTipsWrap.style.display = "block";
            validationTipsWrap.innerText = msg;
            addPostion();
            if(msg){ 
                if(((Math.ceil(getByteLen(msg)/2))*13) < 200){
                    msgWidth = (Math.ceil(getByteLen(msg)/2))*13;
                }else{
                    msgWidth = msgMaxWidth;
                };
            };
            validationTipsWrap.style.width = msgWidth+'px';
        }; 
        // 移除提示信息
        function removeTips(){
            validationTipsWrap.style.display = "none";
            removeClass(el,'validator-input-focus');
            removeClass(el,'validator-input-blur');
            // el.style.borderColor = "#ddd";
            // el.style.color = "#333";
        };
        // 添加提示位置
        function addPostion(){
            if(validatorDirection == "top"){
                validationTipsWrap.style.bottom = el.offsetHeight+7+'px';
            };
            if(validatorDirection == "right"){
                validationTipsWrap.style.top = "0px";
                validationTipsWrap.style.left = el.offsetWidth+7+'px';
            };
            if(validatorDirection == "bottom" || validatorDirection == "" || validatorDirection == null){
                validationTipsWrap.style.top = el.offsetHeight+7+'px';
            };
            if(validatorDirection == "left"){
                validationTipsWrap.style.top = "0px";
                validationTipsWrap.style.right = el.offsetWidth+7+'px';
            };
        };
    }
});
// validateform 自动验证表单指令
Vue.directive('wpg-validator-form',{
    inserted:function(el){
        el.addEventListener('submit',function(e){
            // 是否配置了使用表单提交
            if(el.getAttribute('type')  == 'normal'){ 
                if(checkedFun(el.id)){
                    return true;
                };
            };
            // 阻止默认提交 进行AJAX异步提交
            e.preventDefault();
            if(checkedFun(el.id)){ // 验证通过进行表单提交
            // 防止重复提交
            if(!el.getAttribute('is_submit')){
                el.setAttribute('is_submit',true);
                axiosPost(el.getAttribute('action'),getAjaxPostData(el.getAttribute('id')),function(res){
                    el.removeAttribute('is_submit');
                    msg(res.data.msg,2000);
                });
            };
          };
        });
        // 具体的验证方法 传递这个表单的ID进行验证
        function checkedFun(formId){
            let validatorObj = getValidateObj(formId);
            let remoteStateArr = [];
            for(let i=0; i<validatorObj.length; ++i){
                // 进行验证 传递验证的对象 验证的值 以及验证规则
                let state = validatorValueRules(validatorObj[i],validatorObj[i].value,validatorObj[i].getAttribute('wpg-validator'));
                if(validatorObj[i].getAttribute('remotestate')){
                    remoteStateArr.push(validatorObj[i].getAttribute('remotestate'));
                };
                if(!state){
                    return false;
                    break;
                };
            };
            if(remoteStateArr.length){return false;};
            return true; 
        };
        /***************************************************/
        // 传递 当前对象 值 规则 来进行验证
        function validatorValueRules(obj,elValue,rulesStr){
            let validateRuleArr = rulesStr.split("|");
            for(let i=0; i<validateRuleArr.length; ++i){
                // 处理只传递字符串 require emial phone 类型
                if(validateRuleArr[i].indexOf('(') == -1){
                    if(rules[validateRuleArr[i]].checkFun){
                        if(!rules[validateRuleArr[i]].checkFun(elValue)){
                            // tipMsg(obj,rules[validateRuleArr[i]].message);
                            isTipMsg(obj,validateRuleArr[i],rules[validateRuleArr[i]].message);
                            return false;
                            break;
                        }else{
                            removeTips(obj);
                        };
                    }else if(rules[validateRuleArr[i]].regex){
                        if(!rules[validateRuleArr[i]].regex.test(elValue)){
                            // tipMsg(obj,rules[validateRuleArr[i]].message);
                            isTipMsg(obj,validateRuleArr[i],rules[validateRuleArr[i]].message);
                            return false;
                            break;
                        }else{
                            removeTips(obj);
                        };
                    };
                }else{          
                    // 处理函数类型 拿到方法名
                    let funName = validateRuleArr[i].match(/^[\w]*\(/)[0].replace(/\(/,''); // 拿到设置的方法名
                    let value = validateRuleArr[i].slice(0,validateRuleArr[i].length-1).replace(funName+'(','');// 拿到传递过来的参数
                    // 两种情况特殊处理 regex() 以及 remote()
                    if(funName == 'regex'){ // 处理 regex
                        if(!eval(value).test(elValue)){
                            // tipMsg("请输入正确的格式");
                            isTipMsg(obj,'regex','请输入正确的格式');
                            return false;
                            break;
                        }else{
                            removeTips(obj);
                        };
                    }else if(funName == 'remote'){
                        // 如果失去焦点的时候已经验证过的情况
                        if(obj.getAttribute('remotestate') == 'false'){                            
                            // obj.style.borderColor = "#c33";
                            // obj.style.color = "#cb3333";
                            removeClass(obj,'validator-input-focus');
                            addClass(obj,'validator-input-blur');
                            obj.parentNode.lastChild.style.display = "block";
                            return false;
                        };            
                        // obj.setAttribute('remotestate',false);
                        // tipMsg(obj,"正在验证");
                        // axiosPost(eval(value),{value:elValue},function(res){
                        //   if(res.data.code != 200){
                        //     obj.setAttribute('remotestate',false);
                        //     tipMsg(obj,res.data.msg);
                        //   }else{
                        //     obj.removeAttribute('remotestate');
                        //     removeTips(obj);
                        //   };
                        // });
                    }else{
                        // 处理传递过来的是函数 min() max() minlength() maxlength() 类型 
                        if(rules[funName].checkFun){
                            // 考虑 会传递多个参数 所以现在将传递的参数作为对象进行传递
                            if(!rules[funName].checkFun(elValue,value.split(','))){
                                // tipMsg(rules[funName].message);
                                isTipMsg(obj,funName,rules[funName].message);
                                return false;
                                break;
                            }else{
                                removeTips(obj);
                            };
                        }else if(rules[funName].regex){
                            if(!rules[funName].regex.test(elValue)){
                                // tipMsg(rules[funName].message);
                                isTipMsg(obj,funName,rules[funName].message);
                                return false;
                                break;
                            }else{
                                removeTips(obj);
                            };
                        };
                    };
                };
            };
            return true;
        };
        // 根据From的ID获取当前需要验证的对象
        function getValidateObj(formId){
            let from = document.getElementById(formId);
            let all = from.getElementsByTagName("*");
            let validatorObj = [];
            for(var i=0; i<all.length; ++i){
                if(all[i].getAttribute('name') && all[i].getAttribute('wpg-validator')){
                    validatorObj.push(all[i]);
                };
            };
            return validatorObj;
        };
        /*
         * getAjaxPostData(formid);
         * 根据formid获取表单里面所有设置了 name 的表单元素 以JSON做返回
         */
        function getAjaxPostData(formId){
            let from = document.getElementById(formId);
            let all = from.getElementsByTagName("*");
            let oJson = {};
            for(let i=0; i<all.length; ++i){
                if(all[i].getAttribute('name') && all[i].value){
                    oJson[all[i].getAttribute('name')] = all[i].value;
                };
            };
            return oJson;
        };
        // 产看是否配置了提示
        function isTipMsg(obj,target,defval){
            let msg = obj.getAttribute("validator-errormsg-"+target);
            if(!msg){msg = defval;};
            tipMsg(obj,msg);
        };
        // 显示提示信息
        function tipMsg(obj,msg){
            let msgWidth = null;
            let msgMaxWidth = 200;
            if(((Math.ceil(getByteLen(msg)/2))*13) < 200){msgWidth = (Math.ceil(getByteLen(msg)/2))*13;}else{msgWidth = msgMaxWidth;};
            obj.focus();
            // obj.style.borderColor = "#c33";
            // obj.style.color = "#cb3333";
            removeClass(obj,'validator-input-focus');
            addClass(obj,'validator-input-blur');
            obj.parentNode.lastChild.innerText = msg;
            obj.parentNode.lastChild.style.width = msgWidth+'px';
            obj.parentNode.lastChild.style.display = "block";
        };
        // 获取字节的长度
        function getByteLen(val) {
            let len = 0;
            for(let i = 0; i < val.length; i++){        
                if(val[i].match(/[^\x00-\xff]/ig) != null){
                    len += 2;
                }else{
                    len += 1;
                };
            }
             return len;
        };
        // 移除提示
        function removeTips(obj){
            obj.blur();
            // obj.style.borderColor = "#ddd";
            // obj.style.color = "#333";
            removeClass(obj,'validator-input-focus');
            removeClass(obj,'validator-input-blur');
            obj.parentNode.lastChild.style.display = "none";
        };
    }
});
